﻿using System.Windows.Forms;
using System.Drawing;
using System.Threading;
using System.Collections;
using stanok;

namespace artist
{
    enum cntrl { STOP = 0, FORWARD = 1, BACKWARD = 2, RIGHT = 4, LEFT = 3, UP = 6, DOWN = 5 };

/*
    struct Data3D
    {
        public int x;
        public int y;
        public int z;
        public int type;
    }
    //Описание 3D модели
    struct Model3D
    {
        public int length;
        public int width;
        public int height;
        public ArrayList points;
    }
 * */

    class Artist
    {
        Panel horizontalPanel;
        Panel verticalPanel;
        Model3D model;
        Color clBlock = Color.DarkGray;
        Color clFree  = Color.Yellow;
        Color clRezec = Color.Red;
        Position rezecPosition;


        public Artist(Panel p1, Panel p2)
        {
            horizontalPanel = p1;
            verticalPanel = p2;
            rezecPosition.x = 0;
            rezecPosition.y = 0;
            rezecPosition.z = 2;

        }
        
        public void drawHorizontalPanel(Model3D m, Panel p, int smeshenie, cntrl cnt)
        {
            SolidBrush mySolidBrush = new SolidBrush(Color.Red);
            float w = p.Width, h = p.Height;
            Graphics gr = p.CreateGraphics();

            int temp = 0;
            if (m.length > m.width)
            {
                temp = m.length;
                if (temp < m.height) temp = m.height;
            }
            else
            {
                temp = m.width;
                if (temp < m.height) temp = m.height;
            }


            for (int i = 0; i < m.points.Count; i++)
            {
                Data3D point = (Data3D)m.points[i];
                if (point.type == 0)
                {
                    mySolidBrush = new SolidBrush(Color.Gray);
                    gr.FillRectangle(mySolidBrush, (point.x) * (int)(w / temp), (point.y) * (int)(w / temp), w / temp, w / temp);
                }
            }

            for (int i = 0; i < m.points.Count; i++)
            {
                Data3D point = (Data3D)m.points[i];
                if (point.type == 1)
                {
                    mySolidBrush = new SolidBrush(Color.Blue);
                    gr.FillRectangle(mySolidBrush, (point.x) * (int)(w / temp), (point.y) * (int)(w / temp), w / temp, w / temp);
                }
            }
            for (int i = 0; i < m.points.Count; i++)
            {
                Data3D point = (Data3D)m.points[i];
                if (point.type == 2)
                {
                    mySolidBrush = new SolidBrush(Color.Red);
                    switch (cnt)
                    {
                        case cntrl.RIGHT: gr.FillRectangle(mySolidBrush, (point.x) * (int)(w / temp), (point.y) * (int)(w / temp) + smeshenie, w / temp, w / temp); break;
                        case cntrl.LEFT: gr.FillRectangle(mySolidBrush, (point.x) * (int)(w / temp), (point.y) * (int)(w / temp) - smeshenie, w / temp, w / temp); break;
                        case cntrl.UP: gr.FillRectangle(mySolidBrush, (point.x) * (int)(w / temp), (point.y) * (int)(w / temp), w / temp, w / temp); break;
                        case cntrl.DOWN: gr.FillRectangle(mySolidBrush, (point.x) * (int)(w / temp), (point.y) * (int)(w / temp), w / temp, w / temp); break;
                        case cntrl.FORWARD: gr.FillRectangle(mySolidBrush, (point.x) * (int)(w / temp) + smeshenie, (point.y) * (int)(w / temp), w / temp, w / temp); break;
                        case cntrl.BACKWARD: gr.FillRectangle(mySolidBrush, (point.x) * (int)(w / temp) - smeshenie, (point.y) * (int)(w / temp), w / temp, w / temp); break;
                        case cntrl.STOP: gr.FillRectangle(mySolidBrush, (point.x) * (int)(w / temp), (point.y) * (int)(w / temp), w / temp, w / temp); break;
                    }
                    
                }
            }
        }

        public void drawVerticalPanel(Model3D m, Panel p, int smeshenie, cntrl cnt)
        {
            SolidBrush mySolidBrush = new SolidBrush(Color.Red);
            int w = p.Width, h = p.Height;
            Graphics gr = p.CreateGraphics();

            int temp = 0;
            if (m.length > m.width)
            {
                temp = m.length;
                if (temp < m.height) temp = m.height;
            }
            else
            {
                temp = m.width;
                if (temp < m.height) temp = m.height;
            }
            for (int i = 0; i < m.points.Count; i++)
            {
                Data3D point = (Data3D)m.points[i];
                if (point.type == 0)
                {
                    mySolidBrush = new SolidBrush(Color.Gray);
                    gr.FillRectangle(mySolidBrush, (point.x) * (int)(w / temp), (m.height - 1 - point.z) * (int)(w / temp), w / temp, w / temp);
                }
            }
            for (int i = 0; i < m.points.Count; i++)
            {
                Data3D point = (Data3D)m.points[i];
                if (point.type == 1)
                {
                    mySolidBrush = new SolidBrush(Color.Blue);
                    gr.FillRectangle(mySolidBrush, (point.x) * (int)(w / temp), (m.height - 1 - point.z) * (int)(w / temp), w / temp, w / temp);
                }
            }
            for (int i = 0; i < m.points.Count; i++)
            {
                Data3D point = (Data3D)m.points[i];
                if (point.type == 2)
                {
                    mySolidBrush = new SolidBrush(Color.Red);
                    switch (cnt)
                    {
                        case cntrl.RIGHT: gr.FillRectangle(mySolidBrush, (point.x) * (int)(w / temp), (m.height - 1 - point.z) * (int)(w / temp), w / temp, w / temp); break;
                        case cntrl.LEFT: gr.FillRectangle(mySolidBrush, (point.x) * (int)(w / temp), (m.height - 1 - point.z) * (int)(w / temp), w / temp, w / temp); break;
                        case cntrl.DOWN: gr.FillRectangle(mySolidBrush, (point.x) * (int)(w / temp), (m.height - 1 - point.z) * (int)(w / temp) + smeshenie, w / temp, w / temp); break;
                        case cntrl.UP: gr.FillRectangle(mySolidBrush, (point.x) * (int)(w / temp), (m.height - 1 - point.z) * (int)(w / temp) - smeshenie, w / temp, w / temp); break;
                        case cntrl.FORWARD: gr.FillRectangle(mySolidBrush, (point.x) * (int)(w / temp) + smeshenie, (m.height - 1 - point.z) * (int)(w / temp), w / temp, w / temp); break;
                        case cntrl.BACKWARD: gr.FillRectangle(mySolidBrush, (point.x) * (int)(w / temp) - smeshenie, (m.height - 1 - point.z) * (int)(w / temp), w / temp, w / temp); break;
                        case cntrl.STOP: gr.FillRectangle(mySolidBrush, (point.x) * (int)(w / temp), (m.height - 1 - point.z) * (int)(w / temp), w / temp, w / temp); break;
                    }
                    
                }
            }
        }

        public void draw(Model3D m, int n)
        {
            cntrl cnt;
            //if (n == 0)
                cnt = cntrl.LEFT;
            for (int i = 0; i < 51; i++)
            {
                Thread.Sleep(100);
                drawHorizontalPanel(m, horizontalPanel, i, cnt);
                drawVerticalPanel(m, verticalPanel, i, cnt);
            }    
        }

        public void dravTest(Model3D m)
        {
                model = m;
                dravHorizontalPanel(horizontalPanel);
        }

        public void dravTest(Model3D m, int comand)
        {
            model = m;
            dravHorizontalPanel(horizontalPanel);
            muveRezec(horizontalPanel, comand);
            
            



        }

        private void dravHorizontalPanel( Panel p )
        {
 

            Position point;
            int resLine = 0;
            point.x = 0;
            point.y = 0;
            point.z = 0;

            for(int z = 0; z < model.width; z++ )
                for (int x = 0; x < model.width; x++)
                {
                    point.x = x;
                    point.z = z;
                    resLine = testLineHP( point, model );
                    switch(resLine)
                    {
                        case 0:
                            dravRectangleHorizontal(p, x, z, clFree);
                        break;
                        case 1:
                            dravRectangleHorizontal(p, x, z, clBlock);
                        break;
                        case 2:
                            dravRectangleHorizontal(p, x, z, clRezec);
                            //muveRezec(p, comand);
                          //  if((point.x != backRezecPosition.X) && (point.z != backRezecPosition.Y))
                           //     for(int i = 0; i < 30; i++)

                        break;
                    }


                }

            
            




        }


        //Проверяем линию горизонтальной проэкции
        private int testLineHP(Position p, Model3D m)
        {
            int result = 0;
            Position pb;
            pb.x = p.x;
            pb.y = p.y;
            pb.z = p.z;
            for (int i = 0; i < m.length; i++)
            {
                pb.y = i;
                if (getTypePosition(pb) > 0)
                    return getTypePosition(pb);
            }
            return result = 0;
        }
        //Получение типа позици
        private int getTypePosition(Position p)
        {
            Data3D m;
            int count = model.height*model.length*model.width;
            for (int i = 0; i < count; i++)
            {
                m = (Data3D) model.points[i];
                if ((m.x == p.x) && (m.y == p.y) && (m.z == p.z))
                    return m.type;
            }
            return 0;
        }
        //Рисование квадрата на панели
        private void dravRectangleHorizontal(Panel p, int x, int y, Color cl )
        {
            int w = p.Width, h = p.Height, shift = 0;
            int deltaX =  w / model.width , deltaY =  h / model.height;

            int px1 = 0, py1 = 0;

            SolidBrush mySolidBrush = new SolidBrush(cl);
            Graphics gr = p.CreateGraphics();


            px1 = x * deltaX + shift;           
            py1 = h - (y + 1) * deltaY + shift;


            gr.FillRectangle(mySolidBrush, px1, py1, deltaX - shift, deltaY - shift);


        }
        private void muveRezec(Panel p, int comand)
        {

            int w = p.Width, h = p.Height;
            int deltaX = w / model.width, deltaY = h / model.height;

            int px1 = rezecPosition.x, py1 = rezecPosition.z;
            SolidBrush mySolidBrush = new SolidBrush(Color.Red);            

            Graphics gr = p.CreateGraphics();

            switch (comand)
            {
                case 3:
                    for (int d = 0; d <deltaX; d++)
                    {
                        //dravHorizontalPanel(horizontalPanel);
                        gr.FillRectangle(mySolidBrush, px1 + d, py1, deltaX, deltaY);
                        
                        Thread.Sleep(10);
                        
                    }
                    rezecPosition.x++;
                break;
                case 4:
                    for (int d = 0; d < deltaX; d++)
                    {
                        //dravHorizontalPanel(horizontalPanel);
                        gr.FillRectangle(mySolidBrush, px1 - d, py1, deltaX, deltaY+5);
                        
                        Thread.Sleep(10);
                        
                    }
                    rezecPosition.x -= 1;
                break;
                
                case 5:
                for (int d = 0; d < deltaY; d++)
                {
                    dravHorizontalPanel(horizontalPanel);
                    gr.FillRectangle(mySolidBrush, px1, py1 + d, deltaX, deltaY);

                    Thread.Sleep(10);
                    
                }
                rezecPosition.z -= 1;
                break;
                /*
                default:
                    gr.FillRectangle(mySolidBrush, px1, py1, deltaX, deltaY);
                break;
                 * */}
















        }





    }
}
